﻿/*----------------------------------------------------------------
//  <copyright file="AuditOperationAttribute.cs" company="MicroCloud@151504200868">
//      Copyright © 2020-2024 MicroCloud Corporation, All rights reserved.
//  </copyright>
//  <site>https://gitee.com/chenmm123/microclouds</site>
//  <last-editor>cmm</last-editor>
//  <last-date>2023-07-19 13:50</last-date>
//----------------------------------------------------------------*/

namespace MicroCloud.AspNetCore.Mvc.Filters
{
    #region "操作审计拦截器，负责发起并记录功能的操作日志"
    /// <summary>
    /// 操作审计拦截器，负责发起并记录功能的操作日志
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public sealed class AuditOperationAttribute : ActionFilterAttribute
    {
        #region "继承方法"
        #region "作用于Action执行时"
        /// <summary>
        /// 作用于Action执行时
        /// </summary>
        /// <param name="context"></param>
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            IServiceProvider provider = context.HttpContext.RequestServices;
            IFunction function = context.GetExecuteFunction();
            if (function == null)
            {
                return;
            }
            ScopedDictionary dict = provider.GetRequiredService<ScopedDictionary>();
            // 数据权限有效角色，即有当前功能权限的角色
            IFunctionAuthorization functionAuthorization = provider.GetRequiredService<IFunctionAuthorization>();
            OnlineRole[] userRoles = functionAuthorization.GetOkRoles(function, context.HttpContext.User);
            dict.DataAuthValidRoles = userRoles;

            if (!function.AuditOperationEnabled)
            {
                return;
            }

            AuditOperationEntry operation = new()
            {
                FunctionName = function.Name,
                Ip = context.HttpContext.GetClientIp(),
                UserAgent = context.HttpContext.Request.UserAgent(),
                Method = context.HttpContext.Request.Method,
                ContentType = context.HttpContext.Request.ContentType,
                QueryString = context.HttpContext.Request.QueryString.ToUriComponent(),
                Arguments = context.ActionArguments.ToList().ToJsonString(),
                CreatedTime = DateTime.Now
            };
            if (context.HttpContext.User.Identity.IsAuthenticated && context.HttpContext.User.Identity is ClaimsIdentity identity)
            {
                operation.UserId = identity.GetUserId();
                //operation.UserName = identity.GetUserName();
                //operation.NickName = identity.GetNickName();
            }

            dict.AuditOperation = operation;
        }
        #endregion
        #region "作用于ActionResult执行完成后"
        /// <summary>
        /// 作用于ActionResult执行完成后
        /// </summary>
        /// <param name="context"></param>
        public override void OnResultExecuted(ResultExecutedContext context)
        {
            IServiceProvider provider = context.HttpContext.RequestServices;
            ScopedDictionary dict = provider.GetRequiredService<ScopedDictionary>();
            if (dict.AuditOperation?.FunctionName == null)
            {
                return;
            }
            AjaxResultType type = AjaxResultType.Success;
            string message = context.Exception?.Message;
            string resultData = context.Result?.ToJsonString();
            if (context.Result is JsonResult result1)
            {
                resultData = result1.Value?.ToJsonString();
                if (result1.Value is AjaxResult ajax)
                {
                    type = ajax.Type;
                    message = ajax.Content;
                    resultData = ajax.Data?.ToJsonString();
                }
            }
            else if (context.Result is ObjectResult result2)
            {
                resultData = result2.Value?.ToJsonString();
                if (result2.Value is AjaxResult ajax)
                {
                    type = ajax.Type;
                    message = ajax.Content;
                    resultData = ajax.Data?.ToJsonString();
                }
            }
            //普通请求
            else if (context.HttpContext.Response.StatusCode >= 400)
            {
                type = context.HttpContext.Response.StatusCode switch
                {
                    401 => AjaxResultType.Unauthorized,
                    403 => AjaxResultType.Unauthorized,
                    404 => AjaxResultType.Unauthorized,
                    423 => AjaxResultType.Unauthorized,
                    _ => AjaxResultType.Error,
                };
            }

            dict.AuditOperation.ResultType = type;
            dict.AuditOperation.Message = message;
            dict.AuditOperation.ResultData = resultData;
            dict.AuditOperation.EndedTime = DateTime.Now;
            IUnitOfWork unitOfWork = provider.GetService<IUnitOfWork>();
            unitOfWork?.Dispose();

            //移除当前功能，使保存审计信息的时候不再获取记录变更，审计信息不需要再审计
            dict.Function = null;
            provider.BeginUnitOfWorkTransaction(scopeProvider =>
            {
                IAuditHandler store = scopeProvider.GetService<IAuditHandler>();
                store?.Save(dict.AuditOperation);

            });
        }
        #endregion

        #endregion

    }
    #endregion

}

/* Filter执行顺序
ClassFilter - OnActionExecuting
MethodFilter - OnActionExecuting
MethodFilter - OnActionExecuted
ClassFilter - OnActionExecuted
ClassFilter - OnResultExecuting
MethodFilter - OnResultExecuting
MethodFilter - OnResultExecuted
ClassFilter - OnResultExecuted
*/
